#include <stdarg.h>
#include <stdio.h>
#include "s3c2440.h"
#include "def.h"

#define BOUD_RATE 115200

/*
功能: 初始化串口
参数: 无
*/
void uart_init(void)
{
    GPHCON = ((GPHCON & (~(0xff))) | 0xaa); /* 配置GPH0~3 */
    GPHUP = ((GPHUP & (~(0xff))) | 0xff); /* 禁止上拉 */
    
    ULCON0 = 0x3; /* 一般通信模式，无校验位，1个停止位，8个数据位 */
    UCON0 = 0x5; /* 采用PCLK作为输入工作时钟，采用简单的轮询方式进行数据接收和发送，不开启数据接收超时，数据产生错误时不产生错误状态中断 */
    UFCON0 = 0; /* 不启用FIFO */
    UMCON0 = 0; /* 不使用流控 */
    UBRDIV0 = (int)(50000000.0 / (BOUD_RATE * 16.0)) - 1; /* 通过MPLLCON=0x00043011计算PCLK为50M，设置波特率为115200 */
}

/*
功能: 发送串口数据
参数: u8 c
*/
void uart_send(char c)
{
    while (!(UTRSTAT0 & 0x2));
    UTXH0 = c;
}


/*
功能: 接收串口数据
参数: void
*/
char uart_recv(void)
{
    while (!(UTRSTAT0 & 0x1));
    return URXH0;
}


/*
功能: 发送字符串到串口
参数: u8 *str, 以\0结尾
*/
void uart_send_string(char *str)
{
    while (*str)
        uart_send(*str++);
}


/*
功能: 接收串口字符串
参数: char *str, 输出参数
*/
void uart_recv_string(char *str)
{
    char *temp = str;
    char c;
    
    while ((c = uart_recv()) != '\r')
    {
        if (c == '\b')
        {
            if (temp > str)
            {
                uart_send_string("\b \b"); /* 退格 */
                temp--;
            }
        }
        else
        {
            *temp++ = c;
            uart_send(c); /* 回显 */
        }
    }
    *temp = '\0';
    uart_send_string("\r\n");    
}


/*
功能: 发送10进制数字到串口
参数: u32 n
*/
void uart_send_dec(u32 n)
{
    u32 temp = n;
    int i = 0;
    char out[32];
    
    if (temp == 0)
    {
        uart_send('0');
        return;
    }
    
    while (temp)
    {
        out[i++] = temp % 10 + '0';
        temp /= 10;        
    }
    
    i -= 1;
    while (i >= 0)
    {
        uart_send(out[i--]);
    }
}


/*
功能: 发送16进制数字到串口
参数: u32 n
*/
void uart_send_hex(u32 n)
{
    u32 temp = n;
    int i = 0;
    char out[32];
    
    uart_send_string("0x");
    
    if (temp == 0)
    {
        uart_send('0');
        return;
    }
    
    while (temp)
    {
        if ((temp & 0xf) < 0xa)
        {
            out[i++] = (temp & 0xf) + '0';
        }
        else
        {
            out[i++] = (temp & 0xf) + 'a' - 0xa;
        }        
        temp >>= 4;        
    }
    
    i -= 1;
    while (i >= 0)
    {
        uart_send(out[i--]);
    }    
}


/*
功能: 发送2进制数字到串口
参数: u32 n
*/
void uart_send_bin(u32 n)
{
    u32 temp = n;
    int i = 0;
    char out[32];
    
    uart_send_string("0b");
    
    if (temp == 0)
    {
        uart_send('0');
        return;
    }
    
    while (temp)
    {
        out[i++] = (temp & 0x1) + '0';
        temp >>= 1;        
    }
    
    i -= 1;
    while (i >= 0)
    {
        uart_send(out[i--]);
    }
}


/*
功能: 串口printf
参数: char *fmt
*/
void uart_printf(char *fmt, ...)
{
    va_list ap;
    char str[1024];
    
    va_start(ap, fmt);
    vsprintf(str, fmt, ap);
    uart_send_string(str);
    va_end(ap);
}
